/*-------------------------------------------------------------------------
*************************************************************************
 * @doc CORE
 * @module vidnld.c | Veritalk/Zontalk initiated download functions 
 *
 * Product     :   SoftPay 2000 (Global Payment Methodology).
 * <nl>Developer   :  SoftPay 2000 team 
 * <nl>Notes       :
 *
 * @head3 CORE Functions |
 * @index | CORE
 * @end
 *
 * Copyright (c) 1996-2000 by VeriFone Inc. All rights reserved.
 * 
 * No part of this software may be used, stored, compiled, reproduced,
 * modified, transcribed, translated, transmitted, or transferred, in any form 
 * or by any means whether electronic, mechanical, magnetic, optical, 
 * or otherwise, without the express prior written permission of VeriFone, Inc.
 *
 * Revision History
 * ------------------------------------------------------------------------
 $Log: /APACS30 50/SPK2SIM/Source/Vid/vidnld.c $
 * 
 * 2     11/16/00 4:50p Simon_h2
 * 
 * 1     11/09/00 10:40a Nick_t1
 * 
 * 1     11/01/00 10:48a Nick_t1
 ********************************************************************************/
#define VIDNLD_C

#include <project.h>

#include <aclstr.h>
#include <acldev.h>
#include <txoinc.h>
#include <xmodem.h>
#include <svctxo.h>
#include <svc.h>
#include <stdio.h>
#include <stdlib.h>
#include <aclutil.h>
#include <string.h>
#include <actutil.h>
#include <power.h>
#include <eeslapi.h>

/** /#define DEBUG_VIDNLD*/
#ifdef DEBUG_VIDNLD
#define DEBUG_95
#endif

#include <define.h>
#include <gds.h>
#include <comm.h>
#include <modem.h>
#include <mdmdefs.h>
#include <vidnld.h>
#include <ui.h>
#include <entry.h>
#include <msg.h>
#include <msgfuncs.h>
#include <tct.h>
#include <aat.h>
#include <mdlfuncs.h>
#ifdef MOBITEX_DEFINED
#include <mbtx.h>
#endif
#include <mbtx3.h>
#include <spdebug.h>
#include <modemmsg.h>
#include <protfunc.h>
#include <packet.h>
#include <init.h>
#include <tmadef.h>
#include <syncdial.h>
#include <operate.h>

#define ZON_ENQ_TO 15
#define ZON_ACK_TO 30
#define     MDM_CMD_WAIT_TIME           55          // the dreaded delay

static char* szChangeModemInitSting(char* szInitString,int inSize,VS_BOOL fRemove);


/********************************************************************************************* 
* @func int | inVIDInitModemEnvironmentParam | 
*       Gets the modem param string from CPT (assumption - CPT is
*       loaded) and puts it to the *MI paramater in CONFIG.SYS
*       for the modem engine to get it and use it. 
*
* @parm MODEM_OBJECT *| obModem | 
*       Modem object
*
* @rdesc return values.
* @flag int |  VS_ERR or VS_SUCCESS
* @end
**********************************************************************************************/

int inVIDInitModemEnvironmentParam(MODEM_OBJECT* obModem) {
    /******* /
    int     inRetVal = VS_SUCCESS;
    PFI_MO  pinInitModemEnvironmentParam;

        if ((pinSetModemObject = inGetFunctionPointer(INIT_MODEM_ENV_PARM)) != NULL_PFI)
        {
            inRetVal = pinInitModemEnvironmentParam(obModem);
        }

        return(inRetVal);
    *******/

    return (inVIDDefaultBaseInitModemEnvParam(obModem));
}


int inVIDDefaultBaseInitModemEnvParam(MODEM_OBJECT* obModem) {
    if (srGDS.fTDK_MODEM)
        return (inVIDDefaultTDKInitModemEnvParam(obModem));
    else
        return (inVIDDefaultASPENInitModemEnvParam(obModem));
}


int inVIDDefaultASPENInitModemEnvParam(MODEM_OBJECT* obModem) {
    int result,
    str_len;
    char szModemInitString[MODEM_PARAM_SIZE + 1];
    VS_BOOL fSync = (obModem->shGetDataFormat(obModem->srCPT) == SDLC);

    //pdebug(("--inDefaultASPENInitModemEnvParam--"));
    put_env(SOFTPAY_BASE_MDM_ENV_VAR1, "", 0);
    put_env(SOFTPAY_BASE_MDM_ENV_VAR2, "", 0);
    put_env(MODEM_ENVIRONMENT_VARIABLE, "", 0);
    put_env(SYNC_MODEM_ENVIRONMENT_VARIABLE, "", 0);

    // Load SP*MI1 in Config.sys
    MEMCLR(szModemInitString, MODEM_PARAM_SIZE);
    // Set Factory Default settings
    strcat(szModemInitString, "&F");
    //  Turn echo off, turn verbose response off
    strcat(szModemInitString, "E0V0");
    // (&D2) - DTR drop causes hangup for &Qn settings 
    strcat(szModemInitString, "&D2");
    // (%E0) - Disable line quality monitor and auto-retrain
    strcat(szModemInitString, "%E0"); 
    // Normal speed buffering mode, disables error correction (FORCES &Q6)
    strcat(szModemInitString, "\\N0");  
    // (&K0) - Disable Flow control
    //strcat (szModemInitString, "&K0"); - Factory default setting
    /* Put the string into the SP*MI1 parameter in config.sys */
    str_len = strlen(szModemInitString);
    //pdebug (("OMNI144 %s=%s",SOFTPAY_BASE_MDM_ENV_VAR1,szModemInitString));
    if ((result = put_env(SOFTPAY_BASE_MDM_ENV_VAR1, szModemInitString, strlen(szModemInitString))) != strlen(szModemInitString)) {
        //pdebug(("Result = %d, expected = %d",result,str_len));
        return(result);
    }

    // Load SP*MI2 in Config.sys
    MEMCLR(szModemInitString, MODEM_PARAM_SIZE);
    //kv1 debug, needed for SYNC dialing now
    // (B0/B1) - Select Bell/CCITT Mode
    if (obModem->fGetCommType(obModem->srCPT))
        strcat(szModemInitString, "B1");   /* Set up for Bell */
    else
        strcat(szModemInitString, "B0");   /* Set up for CCITT */


    // (Fn) - Select correct baud rate ranges
    switch (obModem->shGetBaudRate(obModem->srCPT)) {
    case BAUD_300:
        strcat(szModemInitString, "F1");
        break;
    case BAUD_2400:
        strcat(szModemInitString, "F5");
        break;
    case BAUD_4800:
        strcat(szModemInitString, "F6");
        break;
    case BAUD_9600:
        strcat(szModemInitString, "F8");
        break;
    case AUTO_BAUD:
        strcat(szModemInitString, "F0");
    case BAUD_1200:
    default:
        strcat(szModemInitString, "F4");
        break;
    }


    /* Put the string into the SP*MI2 parameter in config.sys */
    str_len = strlen(szModemInitString);
    //pdebug (("OMNI144 %s=%s",SOFTPAY_BASE_MDM_ENV_VAR2,szModemInitString));
    if ((result = put_env(SOFTPAY_BASE_MDM_ENV_VAR2, szModemInitString, strlen(szModemInitString))) != strlen(szModemInitString)) {
        //pdebug(("Result = %d, expected = %d",result,str_len));
        return(result);
    }

    // Load *MI in Config.sys
    MEMCLR(szModemInitString, MODEM_PARAM_SIZE);
    /* append the modem parameters from the CPT file */
    obModem->vdGetModemParam(szModemInitString, obModem->srCPT);
    str_len = strlen(szModemInitString);
    //pdebug (("OMNI144 %s=%s",MODEM_ENVIRONMENT_VARIABLE,szModemInitString));
    if ((result = put_env(MODEM_ENVIRONMENT_VARIABLE, szModemInitString, strlen(szModemInitString))) != strlen(szModemInitString)) {
        //pdebug(("Result = %d, expected = %d",result,str_len));
        return(result);
    }

    // Load SP#AI in Config.sys
    MEMCLR(szModemInitString, MODEM_PARAM_SIZE);
    // (W2) - Set modem to report DCE speed for CONNECT
    strcat(szModemInitString, "W2");
    // (Q0) - Enable result codes
    //strcat(szModemInitString, "Q0");  - factory default
    // (S25=n) - Reset hangup time to default
    //strcat (szModemInitString, "S25=5"); - factory default
    // (&M1) - Select Direct Async
    strcat(szModemInitString, "&M0");       
    /* Put the string into the *MI parameter in config.sys */
    str_len = strlen(szModemInitString);
    //pdebug (("OMNI144 %s=%s",ASYNC_MODEM_ENVIRONMENT_VARIABLE,szModemInitString));
    if ((result = put_env(ASYNC_MODEM_ENVIRONMENT_VARIABLE, szModemInitString, strlen(szModemInitString))) != strlen(szModemInitString)) {
        //pdebug(("Result = %d, expected = %d",result,str_len));
        return(result);
    }

    // Load SP#SI in Config.sys
    MEMCLR(szModemInitString, MODEM_PARAM_SIZE);
    //kv1 debug, moved %C0 %E0 \\N0 to joint
    //strcat (szModemInitString, "%C0\\N0&C1&D2&M1%E1&K0");
    // (&C1) - RLSD follows the state of carrier
    // kv1 debug, should not be req. per barbara/steven
    //strcat (szModemInitString, "&C1");
#ifdef DTR_DIAL     
    // (&M2) - Select Synch connect with Async offline command mode
    //         enable DTR dialing from directory 0
    strcat(szModemInitString, "&M2");
#else
    // (&M1) - Select Synch connect with Async offline command mode
    strcat(szModemInitString, "&M1");
#endif  
    // (S25=n) - Set Sync hangup time to 1 sec., this makes Async to 1 ms.
    strcat(szModemInitString, "S25=1");
    str_len = strlen(szModemInitString);
    //pdebug (("OMNI144 %s=%s",SYNC_MODEM_ENVIRONMENT_VARIABLE,szModemInitString));
    if ((result = put_env(SYNC_MODEM_ENVIRONMENT_VARIABLE, szModemInitString, str_len)) != str_len) {
        //pdebug(("#SI Result = %d, expected = %d",result,str_len));
        return(result);
    }

    return(VS_SUCCESS);
}


int inVIDDefaultTDKInitModemEnvParam(MODEM_OBJECT* obModem) {
    int result,
    str_len;
    char szModemInitString[MODEM_PARAM_SIZE + 1];
    VS_BOOL fBell = obModem->fGetCommType(obModem->srCPT);
    VS_BOOL fSync = (obModem->shGetDataFormat(obModem->srCPT) == SDLC);

    //pdebug(("--inDefaultTDKInitModemEnvParam--"));
    put_env(SOFTPAY_BASE_MDM_ENV_VAR1, "", 0);
    put_env(SOFTPAY_BASE_MDM_ENV_VAR2, "", 0);
    put_env(MODEM_ENVIRONMENT_VARIABLE, "", 0);
    put_env(SYNC_MODEM_ENVIRONMENT_VARIABLE, "", 0);

    MEMCLR(szModemInitString, MODEM_PARAM_SIZE);

    // Turn echo off, turn verbose response off
    strcat(szModemInitString, "E0V0");

    // Select appropriate connection speed(300-2400 baud) and type (BELL/CCITT)
    switch (obModem->shGetBaudRate(obModem->srCPT)) {
    case BAUD_300:
        if (fBell)
            strcat(szModemInitString, "S30=32");
        else
            strcat(szModemInitString, "S30=64");
        break;
    case AUTO_BAUD:
    case BAUD_2400:
        if (fBell)
            strcat(szModemInitString, "S30=52");
        else
            strcat(szModemInitString, "S30=204");
        break;
    default:
    case BAUD_1200:
        if (fBell)
            strcat(szModemInitString, "S30=16");
        else
            strcat(szModemInitString, "S30=8");
        break;
    }

    /* Put the string into the SP*MI1 parameter in config.sys */
    str_len = strlen(szModemInitString);
    //pdebug (("TDK %s=%s",SOFTPAY_BASE_MDM_ENV_VAR1,szModemInitString));
    if ((result = put_env(SOFTPAY_BASE_MDM_ENV_VAR1, szModemInitString, strlen(szModemInitString))) != strlen(szModemInitString)) {
        //pdebug(("Result = %d, expected = %d",result,str_len));
        return(result);
    }

    // Load *MI in Config.sys
    MEMCLR(szModemInitString, MODEM_PARAM_SIZE);
    /* append the modem parameters from the CPT file */
    obModem->vdGetModemParam(szModemInitString, obModem->srCPT);
    str_len = strlen(szModemInitString);
    //pdebug (("TDK %s=%s",MODEM_ENVIRONMENT_VARIABLE,szModemInitString));
    if ((result = put_env(MODEM_ENVIRONMENT_VARIABLE, szModemInitString, strlen(szModemInitString))) != strlen(szModemInitString)) {
        //pdebug(("Result = %d, expected = %d",result,str_len));
        return(result);
    }

#if 0    
    // Load SP#SI in Config.sys
    MEMCLR(szModemInitString, MODEM_PARAM_SIZE);
    // Disable Flow Control (K0), Synchronous Mode (Y1)
    strcpy (szModemInitString, "K0Y1");
    str_len = strlen(szModemInitString);
    //pdebug (("TDK %s=%s",SYNC_MODEM_ENVIRONMENT_VARIABLE,szModemInitString));
    if ((result = put_env(SYNC_MODEM_ENVIRONMENT_VARIABLE, szModemInitString, 
            str_len)) != str_len)
    {
        //pdebug(("#SI Result = %d, expected = %d",result,str_len));
        return(result);
    }
#endif
    // Load SP#AI in Config.sys
    MEMCLR(szModemInitString, MODEM_PARAM_SIZE);
    // (W2) - Set modem to report DCE speed for CONNECT
    strcat(szModemInitString, "W2");
    // (K3) - Enable h/w flow control
    strcat(szModemInitString, "K3");  
    // (V0) - Numeric result codes
    strcat(szModemInitString, "V0"); 
    // (Y6) - applications do not need to change the comm rate based on connection results
    strcat(szModemInitString, "Y6");    //- factory default
    // (Q0) - Enable result codes
    strcat(szModemInitString, "Q0");    //- factory default
    /* Put the string into the *MI parameter in config.sys */
    str_len = strlen(szModemInitString);
    //pdebug (("TDK %s=%s",ASYNC_MODEM_ENVIRONMENT_VARIABLE,szModemInitString));
    if ((result = put_env(ASYNC_MODEM_ENVIRONMENT_VARIABLE, szModemInitString, strlen(szModemInitString))) != strlen(szModemInitString)) {
        //pdebug(("Result = %d, expected = %d",result,str_len));
        return(result);
    }

    return(VS_SUCCESS);
}

/********************************************************************************************* 
* @func int | inOpenMDMCommun | 
*       Open modem and set protocol for Veritalk/Zontalk 
*
* @parm COMM_OBJECT * | pobCommunication | 
*       Pointer to communication object
*
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_SUCCESS
* @end
**********************************************************************************************/
int inOpenMDMCommun(COMM_OBJECT* pobCommunication) {
    MODEM_OBJECT* obModem;
    short shBaud,
    shFormat;
    char szBuffer[50];
    char szInitString[50];

    /** /pdebug(("--inOpenMDMCom--"));*/

    if (inLoadAATRec(0) != VS_SUCCESS)
        return(VS_ERR);

    MEMCLR(szInitString, sizeof(szInitString));

    obModem = (MODEM_OBJECT *) pobCommunication->Data;

    get_env("*MI", szInitString, strlen(szInitString));

    MEMCLR(szBuffer, sizeof(szBuffer));


    if (obModem->hModem) {
        xmdm_close(obModem->hModem, 0, 0);
        obModem->hModem = 0;
        SVC_WAIT(4000);
    }

    shBaud = shGetAutoAnsBaudRate();
    shFormat = shGetAutoAnsFormat();

    obModem->vdSetCommType(1, &obModem->srCPT);
    obModem->vdSetModemParam(szGetAutoAnsInit(), &obModem->srCPT);
    obModem->vdSetModemFastConnect(VS_FALSE, &obModem->srCPT);
    obModem->vdSetBlindDial(VS_FALSE, &obModem->srCPT);
    obModem->vdSetBaudRate(shGetAutoAnsBaudRate(), &obModem->srCPT);
    obModem->vdSetDataFormat(shGetAutoAnsFormat(), &obModem->srCPT);
    if (inVIDInitModemEnvironmentParam(obModem) == VS_ERR) {
        vdSGErrorMessage(MDM_STR_ERR_MSG21);
        return(VS_ERR);
    }

    if (inSPOpenModem(&obModem->hModem, shBaud, shFormat) != VS_SUCCESS)
        return(VS_ERR);

    if (inSPInitModem(obModem->hModem, 0) == HAYES_OK)
        pdebug(("inInitModem"));
    else
        return(VS_ERR);


    return(VS_SUCCESS);
}

/********************************************************************************************* 
* @func int | inForceHangup | 
*       Hangup modem and drop DTR. 
*
* @parm COMM_OBJECT * | pobCommunication | 
*       Pointer to communication object
*
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_SUCCESS
* @end
**********************************************************************************************/
int inForceHangup(COMM_OBJECT* pobCommunication) {
    MODEM_OBJECT* obModem;

    /** /pdebug(("--inForceHangup--"));*/

    obModem = (MODEM_OBJECT *) obCommunication.Data;

    Hangup(obModem->hModem);
    //   xmdm_hangup(obModem->hModem,NO_CLOCK_HANDLE 30);


    return(VS_SUCCESS);
}

/********************************************************************************************* 
* @func int | inSendVIDBuffer | 
*       Send Veritalk/Zontalk Initiated Download packet to host 
*
* @parm COMM_OBJECT * | pobCommunication | 
*       Pointer to communication object
*
* @parm char * | pszBuffer | 
*       Buffer containing packet 
*
* @parm int | inLen | 
*       Length of packet 
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_CARRIER
* @flag int | VS_TIMEOUT
* @flag int | Bytes sent
* @end
**********************************************************************************************/
int inSendVIDBuffer(COMM_OBJECT* pobCommunication,char* pszBuffer,int inLen) {
    int inRetVal;
    MODEM_OBJECT* obModem;
    unsigned long ulDC2Ticks;

    /**/pdebug(("--inSendVIDBuffer--"));/**/
    obModem = (MODEM_OBJECT *) pobCommunication->Data;
    inFlushModemCommunication();
    vdDisplayMessageFromFile(TRANSMITTING_MSG21, STATUS_MSG);

    if ((inRetVal = xmdm_send_data(obModem->hModem, pszBuffer, inLen, 3000)) > 0) {
        if (VS_TRUE) {
            ulDC2Ticks = set_itimeout(NO_CLOCK_HANDLE 30, TM_SECONDS);
            while (MDM_STATUS(obModem->hModem) && CHECK_TIMEOUT(ulDC2Ticks) && pobCommunication->fLinkUp == VS_TRUE) ;
            if (pobCommunication->fLinkUp != VS_TRUE) {
                vdSetTranError(LOST_CARRIER_MSG);
                inRetVal = VS_CARRIER;
            } else if (!CHECK_TIMEOUT(ulDC2Ticks)) {
                vdSetTranError(NO_HOST_RESPONSE);
                inRetVal = VS_TIMEOUT;
            }
        }
        /*
         *      Flush receive buffer post Tx
         */
        inFlushModemCommunication();
    } else
        inRetVal = inProcessPortError(pobCommunication, inRetVal);
    return(inRetVal);
}


/********************************************************************************************* 
* @func int | inSendDLRPacket | 
*       Build and send the DLR Packet to Veritalk/Zontalk. It will tell zontalk/veritalk that 
*       we are ready to do a download. 
*
* @parm COMM_OBJECT * | pobCommunication | 
*       Pointer to communication object
*
*
* @rdesc return values.
* @flag int | Bytes sent
* @end
**********************************************************************************************/
static int inSendDLRPacket(COMM_OBJECT* pobCommunication) {
    char szDLRPacket[50];
    int inPacketLen,
    inRetVal = 1;
    MODEM_OBJECT* obModem;

    obModem = (MODEM_OBJECT *) pobCommunication->Data;

    /* Build "DLRxxxxx" to send to veritalk, to say Download Ready */

    MEMCLR(szDLRPacket, sizeof(szDLRPacket));
    strcpy(&szDLRPacket[1], "DLRxxxxx");

    inPacketLen = inFrameIt(szDLRPacket);

    /* Send the buffer to the modem */ 
    inRetVal = inSendVIDBuffer(pobCommunication, szDLRPacket, inPacketLen);

    return (inRetVal);
}   


/********************************************************************************************* 
* @func int | inGetVIDChar | 
*       Read character from Veritalk/Zontalk 
*
* @parm COMM_OBJECT * | pobCommunication | 
*       Pointer to communication object
*
* @parm UINT | uiTimeOut | 
*       Time out value for receiving character 
*
* @parm char | chChar | 
*       Character to receive 
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_SUCCESS
* @end
**********************************************************************************************/
static int inGetVIDChar(COMM_OBJECT* pobCommunication,UINT uiTimeOut,char chChar) {
    int inRetVal = 1;
    MODEM_OBJECT* obModem;
    char szBuffer[2];
    int inTimer = 0;
    long lnEvent = 0;


    obModem = (MODEM_OBJECT *) pobCommunication->Data;

    vdDisplayMessageFromFile(RECEIVING_MSG21, STATUS_MSG);


    if (inRetVal > 0) {
        /* THIS IS IF SOFTPAY IS THE ONLY APPLICATION !!!!! */
        lnEvent = 0;
        /* Set the required timeout before we start */
        inTimer = set_timer(((long) uiTimeOut * 1000L), EVT_TIMER);

        do {
            inRetVal = xmdm_receive_data(obModem->hModem, szBuffer, 0, 1, (uiTimeOut * 100));
            //pdebug(("szBuffer %02X", szBuffer[0]));           
            //pdebug(("inRetVal %d", inRetVal));            
            if (inRetVal < 0) {
                /* Clear any existing timer */
                clr_timer(inTimer);
                //pdebug(("inRetVal %d", inRetVal));    
                break;
            }

            if (inRetVal == 0) {
                lnEvent = 0;
                while (((lnEvent & EVT_COM3) == 0) && ((lnEvent & EVT_TIMER) == 0)) {
                    /* THIS IS IF SOFTPAY IS THE ONLY APPLICATION !!!!! */
                    lnEvent = wait_event();
                    //pdebug(("event %04x", lnEvent));  
                }


                continue;
            }
            if (szBuffer[0] == chChar) {
                /* Clear any existing timer */
                clr_timer(inTimer);
                break;
            }
        } while ((pobCommunication->fLinkUp == VS_TRUE) && ((peek_event() & EVT_TIMER) == 0) && ((lnEvent & EVT_TIMER) == 0));
        //pdebug(("event %04x", peek_event()));

        /* Clear any existing timer */
        clr_timer(inTimer);

        if (pobCommunication->fLinkUp != VS_TRUE) {
            /*
             *      Set Error Message and Response Message.
             */
            vdSetTranError(LOST_CARRIER_MSG);
            return(VS_ERR);
        }
        if (szBuffer[0] != chChar) {
            inRetVal = inProcessPortError(pobCommunication, inRetVal);
            return(VS_ERR);
        }
    }

    return (VS_SUCCESS);
}   




/********************************************************************************************* 
* @func int | inReadUntilETX | 
*       Read the DL packet from Veritalk/Zontalk 
*
* @parm COMM_OBJECT * | pobCommunication | 
*       Pointer to communication object
*
* @parm char * | pszBuffer | 
*       Buffer containing packet 
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_CARRIER
* @flag int | VS_TIMEOUT
* @flag int | Bytes read
* @end
**********************************************************************************************/
static int inReadUntilETX(COMM_OBJECT* pobCommunication,char* pszBuffer,int inBytesRead) {
    int inRetVal = 1;
    UINT uiTimeOut = 60;
    MODEM_OBJECT* obModem;
    unsigned long ulTicks;

    obModem = (MODEM_OBJECT *) pobCommunication->Data;

    vdDisplayMessageFromFile(RECEIVING_MSG21, STATUS_MSG);


    if (inRetVal > 0) {
        ulTicks = set_itimeout(NO_CLOCK_HANDLE(int)uiTimeOut, TM_SECONDS);
        do {
            inRetVal = xmdm_receive_data(obModem->hModem, &pszBuffer[inBytesRead], 0, 1, (uiTimeOut * 100));
            if (inRetVal < 0)
                break;
            if (pszBuffer[inBytesRead] == ETX) {
                inBytesRead += inRetVal;
                break;
            }
            if (pszBuffer[inBytesRead] > NUL)
                inBytesRead += inRetVal;
        } while (CHECK_TIMEOUT(ulTicks) && pobCommunication->fLinkUp == VS_TRUE);
        if (!CHECK_TIMEOUT(ulTicks)) {
            vdSetTranError(NO_HOST_RESPONSE);
            inRetVal = VS_TIMEOUT; 
            return(VS_ERR);
        } else if (pobCommunication->fLinkUp != VS_TRUE) {
            /*
             *      Set Error Message and Response Message.
             */
            vdSetTranError(LOST_CARRIER_MSG);
            inRetVal = VS_CARRIER; 
            return(VS_ERR);
        }
        if (inRetVal <= 0) {
            inRetVal = inProcessPortError(pobCommunication, inRetVal);
            return(VS_ERR);
        }
    }


    if (inRetVal > 0) {
        ulTicks = set_itimeout(NO_CLOCK_HANDLE(int)uiTimeOut, TM_SECONDS);
        while ((inRetVal = xmdm_receive_data(obModem->hModem, &pszBuffer[inBytesRead], 0, 1, (uiTimeOut * 100))) == 0 && CHECK_TIMEOUT(ulTicks) && pobCommunication->fLinkUp == VS_TRUE);
        if (inRetVal <= 0) {
            inRetVal = inProcessPortError(pobCommunication, inBytesRead);
            return(VS_ERR);
        } else
            inBytesRead += inRetVal;
    }

    /*Return the number of bytes that are read  */
    return (inBytesRead);
}   


/********************************************************************************************* 
* @func int | inReadDLPacket | 
*       Read the DL packet from Veritalk/Zontalk 
*
* @parm COMM_OBJECT * | pobCommunication | 
*       Pointer to communication object
*
* @parm char * | pszBuffer | 
*       Buffer containing packet 
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_CARRIER
* @flag int | VS_TIMEOUT
* @flag int | Bytes read
* @end
**********************************************************************************************/
static int inReadDLPacket(COMM_OBJECT* pobCommunication,char* pszBuffer) {
    int inRetVal = 0;
    int inBytesRead;
    UINT uiTimeOut = 60;
    MODEM_OBJECT* obModem;
    unsigned long ulTicks;

    obModem = (MODEM_OBJECT *) pobCommunication->Data;

    vdDisplayMessageFromFile(RECEIVING_MSG21, STATUS_MSG);
    while (VS_TRUE) {
        ulTicks = set_itimeout(NO_CLOCK_HANDLE(int)uiTimeOut, TM_SECONDS);
        while ((inBytesRead = xmdm_receive_data(obModem->hModem, pszBuffer, 0, 1, (uiTimeOut * 100))) == 0 && CHECK_TIMEOUT(ulTicks) && pobCommunication->fLinkUp == VS_TRUE);
        if (inBytesRead <= 0)
            inRetVal = inProcessPortError(pobCommunication, inBytesRead);
        else if (pszBuffer[0] == STX) {
            inRetVal = inBytesRead;
            break;
        }
    }

    if (inRetVal > 0)
        inBytesRead = inReadUntilETX(pobCommunication, pszBuffer, inBytesRead);

    /*Return the number of bytes that are read  */
    return (inBytesRead);
}   


/********************************************************************************************* 
* @func int | inFrameIt | 
*       Frame packet with STX, ETX and LRC
*
* @parm char * | pszBuffer | 
*       Buffer containing packet 
*
* @rdesc return values.
* @flag int    |  Length of packet
* @end
**********************************************************************************************/
int inFrameIt(char* pszBuffer) {
    unsigned int uiLRC;
    int inLen;

    /*Append the STX, ETX, and the LRC to the packet 
      Can not do a strlen after the LRC is appended just in case the
      LRC is a NULL character */

    pszBuffer[0] = STX;
    inLen = strlen(pszBuffer);

    /* Add end-of-text */
    pszBuffer[inLen] = ETX;
    inLen++;

    /* Add the CRC */
    uiLRC = SVC_CRC_CALC(0, (char *) &pszBuffer[1], inLen);
    pszBuffer[inLen] = (unsigned char) uiLRC;
    inLen++;
    return(inLen);
}


/********************************************************************************************* 
* @func int | inVidActionRequest | 
*        Send the appropriate packet to request a 
*        Call Back 'CB, single phone call host initiated
*        download 'GO', or to abort the download process 'NO'.
*
* @parm COMM_OBJECT * | pobCommunication | 
*       Pointer to communication object
*
* @parm char | chDtype | 
*       Type of download, either partial or full 
*
* @parm VS_BOOL | fCallbackFlag  | 
*       Flag that determines if download is to be done now or later 
*
* @rdesc return values.
* @flag int | Bytes sent
* @end
**********************************************************************************************/

static int inVidActionRequest(COMM_OBJECT* pobCommunication,char chDtype,VS_BOOL fCallbackFlag) {
    char szActionRequest[10];
    int inRetVal,
    inStatus = TRUE,
    inPacketLen;
    TRANSACTION_OBJECT obTran;

    MEMCLR(szActionRequest, sizeof(szActionRequest));
    memset((char *) &obTran, 0x00, sizeof(TRANSACTION_OBJECT));

    /*Refuse to redial if the batch is full */
    if (fBatchEmpty(&obTran, VS_TRUE) != VS_TRUE && (chDtype == 'F' || chDtype == 'f'))
        inStatus = FALSE; /* Do not Redial */    

    if (inStatus == FALSE)
        strcpy(&szActionRequest[1], "NO");
    else if (fCallbackFlag == 1) {
        /*Create packet for Call Back*/
        strcpy(&szActionRequest[1], "CB");
    } else
          /* create the packet for a GO */
        strcpy(&szActionRequest[1], "GO");

    inPacketLen = inFrameIt(szActionRequest);

    /* Send the packet ; send 'GO', 'NO' or 'CB' */
    /* Send the buffer to the modem */
    inRetVal = inSendVIDBuffer(pobCommunication, szActionRequest, inPacketLen);
    if (inRetVal > 0) {
        if (inStatus == FALSE)
            inRetVal = 2;
        else
            inRetVal = 1;
    }
    return (inRetVal);
}



/********************************************************************************************* 
* @func int | inWaitForOK | 
*       This function waits for OK and ENQ from Veritalk. 
*
* @parm COMM_OBJECT * | pobCommunication | 
*       Pointer to communication object
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_SUCCESS
* @end
**********************************************************************************************/
static int inWaitForOK(COMM_OBJECT* pobCommunication) {
    int inRetVal = VS_SUCCESS;
    int inBytesRead;
    char szBuffer[10];
    UINT uiTimeOut = 60;
    MODEM_OBJECT* obModem;
    unsigned long ulTicks;
    char chCharBuf[2];

    obModem = (MODEM_OBJECT *) pobCommunication->Data;

    /* Set response timer  */
    while (VS_TRUE) {
        ulTicks = set_itimeout(NO_CLOCK_HANDLE(int)uiTimeOut, TM_SECONDS);
        while ((inBytesRead = xmdm_receive_data(obModem->hModem, szBuffer, 0, 1, (uiTimeOut * 100))) == 0 && CHECK_TIMEOUT(ulTicks) && pobCommunication->fLinkUp == VS_TRUE);
        if (!CHECK_TIMEOUT(ulTicks)) {
            vdSetTranError(NO_HOST_RESPONSE);
            return(VS_TIMEOUT);
        } else if (pobCommunication->fLinkUp != VS_TRUE) {
            /*
             *      Set Error Message and Response Message.
             */
            vdSetTranError(LOST_CARRIER_MSG);
            return(VS_CARRIER);
        }
        if (szBuffer[0] == ENQ)
            break;
        if (szBuffer[0] == STX) {
            inBytesRead = inReadUntilETX(pobCommunication, szBuffer, inBytesRead);
            if (inBytesRead > 2) {
                if (!strncmp(&szBuffer[1], "OK", 2)) {
                    chCharBuf[0] = ACK;
                    chCharBuf[1] = NUL;
                    if (inSendVIDBuffer(pobCommunication, chCharBuf, 1) != 1) {
                        if (inForceHangup(&obCommunication) == VS_ERR)
                            return (VS_ERR);
                        vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                        return(VS_ERR);
                    }
                    break;
                } else {
                    if (inForceHangup(&obCommunication) == VS_ERR)
                        return (VS_ERR);
                    vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                    return(VS_ERR);
                }
            }
        }
    }

    return (inRetVal);
}   


/********************************************************************************************* 
* @func int | inParseDLPacket | 
*       Parse DL packet from Veritalk/Zontalk and set *Z parameters.
*
* @parm char * | pszBuffer | 
*       Buffer containing packet 
*
* @rdesc return values.
* @flag int    |  VS_TRUE
* @flag int    |  VS_FALSE
* @flag int    |  VS_ERR
* @end
**********************************************************************************************/
int inParseDLPacket(char* pszBuffer) {
    char* ptr;


    if ((ptr = strchr(pszBuffer, 0x1C)) != NUL)
        return (inParseVeritalkDLPacket(pszBuffer));
    else if ((ptr = strchr(pszBuffer, 0x7e)) != NUL)
        return (inParseZontalkDLPacket(pszBuffer));
    return(VS_ERR);
}



/********************************************************************************************* 
* @func int | inParseVeritalkDLPacket | 
*       Parse DL packet from Veritalk and set *ZA and *ZT.
*
* @parm char * | pszBuffer | 
*       Buffer containing packet 
*
* @rdesc return values.
* @flag int    |  VS_TRUE
* @flag int    |  VS_FALSE
* @flag int    |  VS_ERR
* @end
**********************************************************************************************/
int inParseVeritalkDLPacket(char* pszBuffer) {
    int inRetVal = VS_ERR;
    int inBytes;
    char szAppName[8];
    char szTermID[11];
    char szPhoneNo[30];
    char szEnvAccessCode[12];
    char szEnvAppName[8];
    char szEnvTermID[11];
    char* ptr,
    * pszTermID,
    * pszPhoneNo;


    if ((ptr = strchr(pszBuffer, 0x1C)) != NUL) {
        ptr++;                  /* Access Code */
        inBytes = get_env("*ZS", szEnvAccessCode, sizeof(szEnvAccessCode));
        if (inBytes > 0 && *ptr != 0x1C)/* if env var has value and packet has access code */
            if (strncmp(ptr, szEnvAccessCode, inBytes))
                return(VS_ERR);

        if ((ptr = strchr(ptr, 0x1C)) != NUL) {
            ptr++;                  /* Fam Name */
            /*            
                        if (strncmp(ptr, "O3300", 5))
                        
                        { display family name mismatch * /
                            return(VS_ERR);
                        }
            */            
            if ((ptr = strchr(ptr, 0x1C)) != NUL) {
                ptr++;                  /* Appl Name */
                inBytes = get_env("*ZA", szEnvAppName, sizeof(szEnvAppName));
                if (inBytes > 0 && *ptr != 0x1C)/* if env var has value and packet has App Name */
                    if (strncmp(ptr, szEnvAppName, inBytes))
                        return(VS_ERR);
                MEMCLR(szAppName, sizeof(szAppName));
                strncpy(szAppName, ptr, 7);
                put_env("*ZA", szAppName, strlen(szAppName));

                if ((ptr = strchr(ptr, 0x1C)) != NUL) {
                    ptr++;                  /* Term Id */
                    inBytes = get_env("*ZT", szEnvTermID, sizeof(szEnvTermID));
                    if (inBytes > 0 && *ptr != 0x1C)/* if env var has value and packet has term ID */
                        if (strncmp(ptr, szEnvTermID, inBytes))
                            return(VS_ERR);
                    MEMCLR(szTermID, sizeof(szTermID));
                    strncpy(szTermID, ptr, 10);
                    if ((pszTermID = strchr(szTermID, 0x1C)) != NUL)
                        pszTermID[0] = '\0';                        
                    if ((pszTermID = strchr(szTermID, 0x03)) != NUL)
                        pszTermID[0] = '\0';
                    put_env("*ZT", szTermID, strlen(szTermID));
                    inRetVal = VS_TRUE;

                    if ((ptr = strchr(ptr, 0x1C)) != NUL) {
                        ptr++;                  /* Phone No */
                        MEMCLR(szPhoneNo, sizeof(szPhoneNo));
                        strncpy(szPhoneNo, ptr, 30);
                        if ((pszPhoneNo = strchr(szPhoneNo, 0x03)) != NUL)
                            pszPhoneNo[0] = '\0';
                        put_env("*ZP", szPhoneNo, strlen(szPhoneNo));
                    }
                }
            }
        }
    }
    return(inRetVal);
}


/********************************************************************************************* 
* @func int | inParseZontalkDLPacket | 
*       Parse DL packet from Zontalk and set *ZA and *ZT.
*
* @parm char * | pszBuffer | 
*       Buffer containing packet 
*
* @rdesc return values.
* @flag int    |  VS_TRUE
* @flag int    |  VS_FALSE
* @flag int    |  VS_ERR
* @end
**********************************************************************************************/
int inParseZontalkDLPacket(char* pszBuffer) {
    int inRetVal = VS_ERR;
    int inBytes;
    char szAppName[8];
    char szTermID[11];
    char szPhoneNo[30];
    char szEnvAccessCode[12];
    char szEnvAppName[8];
    char szEnvTermID[11];
    char* ptr,
    * pszTermID,
    * pszPhoneNo;


    if ((ptr = strchr(pszBuffer, 0x7e)) != NUL) {
        ptr++;                  /* Access Code */
        inBytes = get_env("*ZS", szEnvAccessCode, sizeof(szEnvAccessCode));
        if (inBytes > 0 && *ptr != 0x1C)/* if env var has value and packet has access code */
            if (strncmp(ptr, szEnvAccessCode, inBytes))
                return(VS_ERR);

        if ((ptr = strchr(ptr, 0x7e)) != NUL) {
            ptr++;                  /* Fam Name */
            /*            
                        if (strncmp(ptr, "O3300", 5))
                        { display family name mismatch * /
                            return(VS_ERR);
                        }
            */            
            if ((ptr = strchr(ptr, 0x7e)) != NUL) {
                ptr++;                  /* Appl Name */
                inBytes = get_env("*ZA", szEnvAppName, sizeof(szEnvAppName));
                if (inBytes > 0 && *ptr != 0x1C)/* if env var has value and packet has App Name */
                    if (strncmp(ptr, szEnvAppName, inBytes))
                        return(VS_ERR);
                MEMCLR(szAppName, sizeof(szAppName));
                strncpy(szAppName, ptr, 7);
                put_env("*ZA", szAppName, strlen(szAppName));

                if ((ptr = strchr(ptr, 0x7e)) != NUL) {
                    ptr++;                  /* Term Id */
                    inBytes = get_env("*ZT", szEnvTermID, sizeof(szEnvTermID));
                    if (inBytes > 0 && *ptr != 0x1C)/* if env var has value and packet has term ID */
                        if (strncmp(ptr, szEnvTermID, inBytes))
                            return(VS_ERR);
                    MEMCLR(szTermID, sizeof(szTermID));
                    strncpy(szTermID, ptr, 10);
                    if ((pszTermID = strchr(szTermID, 0x7e)) != NUL)
                        pszTermID[0] = '\0';
                    if ((pszTermID = strchr(szTermID, 0x03)) != NUL)
                        pszTermID[0] = '\0';
                    put_env("*ZT", szTermID, strlen(szTermID));
                    inRetVal = VS_FALSE;


                    if ((ptr = strchr(ptr, 0x7e)) != NUL) {
                        ptr++;                  /* Phone No */
                        MEMCLR(szPhoneNo, sizeof(szPhoneNo));
                        strncpy(szPhoneNo, ptr, 30);
                        if ((pszPhoneNo = strchr(szPhoneNo, 0x03)) != NUL)
                            pszPhoneNo[0] = '\0';
                        put_env("*ZP", szPhoneNo, strlen(szPhoneNo));
                    }
                }
            }
        }
    }
    return(inRetVal);
}

/********************************************************************************************* 
* @func int | inVeritalkDownload | 
*       This function checks for carrier. If found zontalk download is attempted.
*
* @parm TRANSACTION_OBJECT * |pobTran | 
*       Transaction object.
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_SUCCESS
* @end
**********************************************************************************************/
int inVeritalkDownload(TRANSACTION_OBJECT* pobTran) {
    unsigned char stat_map;
    MODEM_OBJECT* obModem;
    signed int inRetVal;
    char szBuffer[75];
    char chCharBuf[2];
    int inLRCPacketSize;
    unsigned int uiLrcChar;
    unsigned long ulDC2Ticks;
    char chPF;
    int inVeriTalk;
    VS_BOOL fCallbackFlag = 0;
    int i;
    int inStatus;
    short inIdleTimeOut;                        /* Local field to save Idle Timeout-Seconds */
    char szPhoneNo[30];
    int inBytes;

    obModem = (MODEM_OBJECT *) obCommunication.Data;
    obCommunication.fLinkUp = VS_FALSE;

    MEMCLR(szBuffer, sizeof(szBuffer));

    vdDisplayMessageFromFile(LAN_WAIT_ERR_MSG, STATUS_MSG);

    stat_map = MDM_CTS;
    if (xmdm_check_status(obModem->hModem, stat_map) != 1) {
        inForceHangup(&obCommunication);
        inFlushModemCommunication();
        return(VS_ERR);
    }
    stat_map = MDM_DCD;
    ulDC2Ticks = set_itimeout(NO_CLOCK_HANDLE 15, TM_SECONDS);

    while (xmdm_check_status(obModem->hModem, stat_map) != 1 && CHECK_TIMEOUT(ulDC2Ticks) != 0);

    if (CHECK_TIMEOUT(ulDC2Ticks) != 0)  // No timeout
    {
#ifdef TMA_DEFINED
        vdIncMICounter(MI_NO_INCOMING_CALLS);
#endif  
        inIdleTimeOut = inGetIdleTimeOut();
        vdSetIdleTimeOut(20);
        if ((inRetVal = obDisp.inDO_ChooseOne(NULL, pchGetMsg(STOP_DOWNLOAD_MSG15), pchGetMsg(YESNO_MSG5x), 2, NULL_PFI)) == KEY_YES) {
            vdSetIdleTimeOut(inIdleTimeOut);
            inFlushModemCommunication();
            if (inForceHangup(&obCommunication) == VS_ERR)
                return (VS_ERR);
            inOpenMDMCommun(&obCommunication);
            return(VS_ERR);
        }
        vdSetIdleTimeOut(inIdleTimeOut);
        obCommunication.fLinkUp = VS_TRUE;
    } else {
        inForceHangup(&obCommunication);
        inFlushModemCommunication();
        return(VS_ERR);
    }

    if (obCommunication.fLinkUp != VS_TRUE) {
        inFlushModemCommunication();
        return(VS_ERR);
    }

    ulDC2Ticks = set_itimeout(NO_CLOCK_HANDLE 30, TM_SECONDS);
    do {
        if (xmdm_input_pending(obModem->hModem) == 1) {
            if (inGetVIDChar(&obCommunication, ZON_ENQ_TO, ENQ) != VS_SUCCESS) {
                if (inForceHangup(&obCommunication) == VS_ERR)
                    return (VS_ERR);
                vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                return(VS_ERR);
            }
            inRetVal = inSendDLRPacket(&obCommunication);   
            if (inRetVal < 0) {
                if (inForceHangup(&obCommunication) == VS_ERR)
                    return (VS_ERR);
                vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                return(VS_ERR);
            }

            if (inGetVIDChar(&obCommunication, ZON_ACK_TO, ACK) != VS_SUCCESS) {
                if (inForceHangup(&obCommunication) == VS_ERR)
                    return (VS_ERR);
                vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                return(VS_ERR);
            }

            MEMCLR(szBuffer, sizeof(szBuffer));
            inRetVal = inReadDLPacket(&obCommunication, szBuffer);
            inLRCPacketSize = (inRetVal - 2);
            if (inRetVal > 0) {
                /*Calculate without STX & LRC */

                uiLrcChar = SVC_CRC_CALC(0, &szBuffer[1], inLRCPacketSize);
                if ((char) uiLrcChar == szBuffer[inRetVal - 1]) {
                    chCharBuf[0] = ACK;
                    chCharBuf[1] = NUL;
                    if (inSendVIDBuffer(&obCommunication, chCharBuf, 1) != 1) {
                        if (inForceHangup(&obCommunication) == VS_ERR)
                            return (VS_ERR);
                        vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                        return(VS_ERR);
                    }
                    szBuffer[inLRCPacketSize + 2] = NULL_CH;
                } else {
                    chCharBuf[0] = NAK;
                    chCharBuf[1] = NUL;
                    inSendVIDBuffer(&obCommunication, chCharBuf, 1);
                    inRetVal = 0;               /* Decrement Retry count and read*/
                    MEMCLR(szBuffer, sizeof(szBuffer));
                    if (inForceHangup(&obCommunication) == VS_ERR)
                        return (VS_ERR);
                    vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                    return(VS_ERR);
                }
            }
            if (inRetVal > 0 && inRetVal < sizeof(szBuffer)) {
                chPF = szBuffer[3] ;  /* This should get the type p partial or f full */
                if ((inVeriTalk = inParseDLPacket(szBuffer)) == VS_ERR) {
                    if (inForceHangup(&obCommunication) == VS_ERR)
                        return (VS_ERR);
                    vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                    return VS_ERR;
                }
            }

            /*Wait for an ENQ from the host */
            if (inRetVal > 0) {
                if (inGetVIDChar(&obCommunication, ZON_ENQ_TO, ENQ) != VS_SUCCESS) {
                    if (inForceHangup(&obCommunication) == VS_ERR)
                        return (VS_ERR);
                    vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                    return(VS_ERR);
                }
            }

            if (inRetVal > 0)
                inRetVal = inVidActionRequest(&obCommunication, chPF, fCallbackFlag);
            inStatus = inRetVal;

            /*Wait for an Ack from Veritalk */
            if (inRetVal > 0)
                if (inGetVIDChar(&obCommunication, ZON_ACK_TO, ACK) != VS_SUCCESS) {
                    if (inForceHangup(&obCommunication) == VS_ERR)
                        return (VS_ERR);
                    vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                    return(VS_ERR);
                }

            /*Wait for the OK response from Veritalk */
            if (inRetVal > 0 && inVeriTalk == VS_TRUE)
                if (inWaitForOK(&obCommunication) != VS_SUCCESS) {
                    if (inForceHangup(&obCommunication) == VS_ERR)
                        return (VS_ERR);
                    vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                    return(VS_ERR);
                }


            if (inStatus == 2) {
                if (inForceHangup(&obCommunication) == VS_ERR)
                    return (VS_ERR);
                vdDisplayMessageFromFile(BATCH_NOT_EMPTY_ERR_MSG15, ERROR_MSG);
                vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                return(VS_ERR);
            }

            /*Close the port and initialize the handle*/
            if (fCallbackFlag == 1) {
                (void) close(obModem->hModem);
                obModem->hModem = 0;
            }

            /*Now Call SVC_ZONTALK to get the Download*/

            if (fCallbackFlag == 1) {
                /*Pause to allow the Zontalk modem to resych
                If necessary, redial three times, if this is a partial
                'p' and we are successful then we will escape and return
                to idle */

                inBytes = get_env("*ZP", szPhoneNo, sizeof(szPhoneNo));
                if (inBytes == 0)/* if no phone no in env var  */ {
                    MEMCLR(szPhoneNo, sizeof(szPhoneNo));
                    vdSetNextLineEntry();   /* for 3200 */     
                    if (inEnterWithMessage(ENTER_PHONE_NO_MSG15, SCROLL_DISPLAY_FALSE, szPhoneNo, INPUT_ALNUMS, sizeof(szPhoneNo), NULL_PFI) > 0)
                        put_env("*ZP", szPhoneNo, strlen(szPhoneNo));
                    else {
                        /* No phone number for redial */
                        return (VS_ERR);
                    }
                    vdClrNextLineEntry();
                }            
                for (i = 0; i < 3; i++) {
                    SVC_WAIT(3000);
                    if (chPF == 'F' || chPF == 'f')
                        inRetVal = inFullDownloadOperation(pobTran);
                    else
                        inRetVal = inPartDownloadOperation(pobTran);
                    //                    inRetVal = inBeginDownload( chPF );
                    if (act_kbd_pending_test(KEY_CANCEL))
                        break; 
                    if (inRetVal > 0)
                        break;
                }
            } else {
                /*Zontalk will be initiated with same phone call
                 */
                SVC_WAIT(1000);

                if ((inRetVal = xmdm_set_protocol(obModem->hModem, shGetAutoAnsBaudRate(), Fmt_A8N1)) < 0)
                    //                if ((inRetVal = xmdm_set_protocol(obModem->hModem, Rt_2400, Fmt_A8N1)) < 0)
                {
                    if (inForceHangup(&obCommunication) == VS_ERR)
                        return (VS_ERR);
                    inOpenMDMCommun(&obCommunication);
                    return(VS_ERR);
                }

                SVC_WAIT(1000);
                inRetVal = SVC_ZONTALK(chPF + 0x01/*NO_DIAL*/);
                if (inRetVal != VS_SUCCESS) {
                    if (inForceHangup(&obCommunication) == VS_ERR)
                        return (VS_ERR);
                    inOpenMDMCommun(&obCommunication);
                    vdDisplayMessageFromFile(DOWNLINE_LOAD_ERR_MSG, ERROR_MSG);
                    return(VS_ERR);
                } else
                    vdDisplayMessageFromFile(DOWNLINE_LOAD_SUCCESS_MSG, STATUS_MSG);
                inOpenMDMCommun(&obCommunication);
                if (obDisp.inTerminalType == TERMINAL_OMNI_3200) {
                    resetdisplay("k2_6x8.vft", 0); /* set to 3200 default font */
                }
            }
        }
    } while (CHECK_TIMEOUT(ulDC2Ticks) && obCommunication.fLinkUp == VS_TRUE) ;

    return(VS_SUCCESS);
}

/********************************************************************************************* 
* @func int | inAutoAnswerInit | 
*       This function opens the modem and sets the modem to auto answer
*
* @parm TRANSACTION_OBJECT * |pobTran | 
*       Transaction object.
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_SUCCESS
* @end
**********************************************************************************************/

int inAutoAnswerInit(TRANSACTION_OBJECT* pobTran) {
    MODEM_OBJECT* obModem;
    int inRetVal = VS_SUCCESS;

    obModem = (MODEM_OBJECT *) obCommunication.Data;
    if (fGetAutoAnswer()) {
        if (srGDS.fLandLine) {
            if (srGDS.fHandHeld)
                while (get_dock_status() == HANDHELD_UNDOCKED && inRetVal == VS_SUCCESS) {
                    if (obDisp.blCfigEdit == VS_TRUE)
                        vdDisplayWarningString("Must Dock Termnl");
                    else
                        vdDisplayWarningMsg(MUST_DOCK_TERMINAL_MSG21);

                    if (act_kbd_pending_test(KEY_CANCEL)) {
                        vdSetTranError(TXN_CANCELLED);
                        if (obDisp.blCfigEdit == VS_TRUE)
                            return(VS_ERR);
                        else {
                            vdDisplayWarningMsg(MODEM_TIMEOUT_MSG21);
                            // Can't return error to cold boot or we
                            // can never boot up
                            return(VS_SUCCESS);
                        }
                    } /* end if cancel pressed */
                } /* end if handheld terminal */
        } /* end if landline modem exists */

        //vdDisplayMessageFromFile( MODEM_CHECK_MSG21, STATUS_MSG);

        if (inOpenMDMCommun(&obCommunication) == VS_ERR) {
            vdDisplayWarningMsg(OPEN_MDM_ERROR_MSG21);
            if (obDisp.blCfigEdit == VS_TRUE)
                return(VS_ERR);
            else
                return(VS_SUCCESS);
        }
        inAutoAnswerOn(obModem->hModem);
    } /* end if TCT auto answer ON */
    return(VS_SUCCESS);
} /* end if inAutoAnswerInit() */

/********************************************************************************************* 
* @func int | inAutoAnswerOn | 
*       This function sets the modem to auto answer
*
* @parm int | hModem | 
*       Open modem handle
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_SUCCESS
* @end
**********************************************************************************************/

int inAutoAnswerOn(int hModem) {
    char szBuffer[50];
    int xbytes; {
        MEMCLR(szBuffer, sizeof(szBuffer));
        szChangeModemInitSting(szBuffer, sizeof(szBuffer), 0);
        xbytes = xhayes_send_cmd(hModem, szBuffer);
        if (xbytes != (strlen(szBuffer) + XHAYES_STRING_FRAME))
            return(VS_ERR);
        else
            xhayes_response(hModem, NO_CLOCK_HANDLE 7);
    }            
    inFlushModemCommunication();
    return(VS_SUCCESS);
}

/********************************************************************************************* 
* @func int | inAutoAnswerOff | 
*       This function sets the modem to NOT auto answer
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_SUCCESS
* @end
**********************************************************************************************/
int inAutoAnswerOff(void) {
    MODEM_OBJECT* obModem;
    char szBuffer[10];
    int xbytes;

    if (fGetAutoAnswer()) {
        obModem = (MODEM_OBJECT *) obCommunication.Data;
        szBuffer[0] = 'S';
        szBuffer[1] = '0';
        szBuffer[2] = '=';
        szBuffer[3] = '0';
        szBuffer[4] = '\0';
        xbytes = xhayes_send_cmd(obModem->hModem, szBuffer);
        if (xbytes == (strlen(szBuffer) + XHAYES_STRING_FRAME)) {
            xhayes_response(obModem->hModem, NO_CLOCK_HANDLE 7);
            inFlushModemCommunication();
        }
        xmdm_close(obModem->hModem, 0, 0);
        obModem->hModem = 0;
    }
    return(VS_SUCCESS);
}


/********************************************************************************************* 
* @func int | inAutoAnswerReset | 
*       This function sets the modem to auto answer off
*
* @parm int | hModem | 
*       Open modem handle
*
* @rdesc return values.
* @flag int | VS_ERR 
* @flag int | VS_SUCCESS
* @end
**********************************************************************************************/

int inAutoAnswerReset(int hModem) {
    char szBuffer[50];

    if (inLoadAATRec(0) != VS_SUCCESS)
        return(VS_ERR);

    memset(szBuffer, 0x00, sizeof(szBuffer));
    strcpy(szBuffer, szGetAutoAnsInit());
    put_env(MODEM_ENVIRONMENT_VARIABLE, szBuffer, strlen(szBuffer));
    if ((hModem = xmdm_init(hModem, DEV_MODEM, NO_CLOCK_HANDLE 30, Rt_1200, Fmt_A7E1)) < 0) {
        /** /pdebug(("inOpenResult = %d", result));*/
        return(VS_ERR);
    }
    xmdm_close(hModem, 0, 0);
    return(VS_SUCCESS);
}

static char* szChangeModemInitSting(char* szInitString,int inSize,VS_BOOL fRemove) {
    int inOffset = 0;
    VS_BOOL fFoundit = VS_FALSE;
    char szNumRings[3];
    char* ptr;

    inLoadAATRec(0);

    if (is37xx() == TRUE)
        szInitString[0] = '\0';
    else
        strcpy(szInitString, szGetAutoAnsInit());
    if ((ptr = strstr(szInitString, "S0=")) != NULL) {
        pdebug(("Not setting num rings"));
        if (!fRemove)
            return szInitString;

        memmove(ptr, ptr + 4, strlen(ptr) + 1);
    } else {
        pdebug(("Setting num rings"));
        int2str(szNumRings, inGetNumOfRings());
        strcat(szInitString, "S0=");
        strcat(szInitString, szNumRings);
    }
    put_env("*MI", szInitString, strlen(szInitString));
    return szInitString;
}


int inHostInitiatedDownload(TRANSACTION_OBJECT* pobTran) {
    MODEM_OBJECT* obModem;
    VS_BOOL fRadioHost = VS_FALSE;
    int inRetVal = VS_SUCCESS;
    char szBuffer[10];
    int xbytes;

    obModem = (MODEM_OBJECT *) obCommunication.Data;

    // They can set up their terminal, mostly radio comm, to get a
    // landline Host Initiated Download (VeriCenter, VeriTalk, etc)
    // at night but only if its docked.

    if (srGDS.fLandLine) {
        if (srGDS.fHandHeld)
            while (get_dock_status() == HANDHELD_UNDOCKED && inRetVal == VS_SUCCESS) {
                vdDisplayWarningMsg(MUST_DOCK_TERMINAL_MSG21);
                if (act_kbd_pending_test(KEY_CANCEL)) {
                    vdSetTranError(TXN_CANCELLED);
                    return(BRANCH_EXIT);
                }
            }
    } /* end if landline modem exists */

    vdDisplayMessageFromFile(LAN_WAIT_ERR_MSG, STATUS_MSG);

#ifdef MOBITEX_DEFINED

    inRetVal = inGetRadioCommHost();

    if (inRetVal != VS_ERR && srGDS.fWirelessModem) {
        fRadioHost = VS_TRUE;
        inDeInitRadioModem();
    } /* end if set up for radio */

#endif

    inInitializeComm(MODEM_COMM);
    obModem = (MODEM_OBJECT *) obCommunication.Data;

    if (inOpenMDMCommun(&obCommunication) == VS_ERR) {
        vdDisplayMessageFromFile(OPEN_MDM_ERROR_MSG21, WARNING_MSG);
        return(BRANCH_EXIT);
    }

    inRetVal = 0;
    vdDisplayMessageFromFile(WAIT_FOR_HOST_MSG, STATUS_MSG);

    // Wait for CLEAR key or Com3 event
    while ((inRetVal == 0) && (wait_event() != EVT_COM3)) {
        SVC_WAIT(10);
        inRetVal = act_kbd_pending_test(KEY_CANCEL);
    }


    if (inRetVal == 0)  // Cancel not pressed so we got a call !!
        inVeritalkDownload(pobTran);

    clrscr();
    vdDisplayMessageFromFile(LAN_WAIT_ERR_MSG, STATUS_MSG);

#ifdef MOBITEX_DEFINED

    if (fRadioHost) {
        memset(szBuffer, 0x00, sizeof(szBuffer));
        szBuffer[0] = 'S';
        szBuffer[1] = '0';
        szBuffer[2] = '=';
        szBuffer[3] = '0';
        szBuffer[4] = '\0';
        xbytes = xhayes_send_cmd(obModem->hModem, szBuffer);
        if (xbytes == (strlen(szBuffer) + XHAYES_STRING_FRAME)) {
            xhayes_response(obModem->hModem, NO_CLOCK_HANDLE 7);
            inFlushModemCommunication();
        }
        xmdm_close(obModem->hModem, 0, 0);
        obModem->hModem = 0;

        inInitRadioModem();
    } /* end if we were a radio host */
    else
    #endif
    {
        if (!fGetAutoAnswer()) {
            memset(szBuffer, 0x00, sizeof(szBuffer));
            szBuffer[0] = 'S';
            szBuffer[1] = '0';
            szBuffer[2] = '=';
            szBuffer[3] = '0';
            szBuffer[4] = '\0';
            xbytes = xhayes_send_cmd(obModem->hModem, szBuffer);
            if (xbytes == (strlen(szBuffer) + XHAYES_STRING_FRAME)) {
                xhayes_response(obModem->hModem, NO_CLOCK_HANDLE 7);
                inFlushModemCommunication();
            }
            xmdm_close(obModem->hModem, 0, 0);
            obModem->hModem = 0;
        }
    } /* end else not radio host */

    return(BRANCH_EXIT);
} /* end func inHostInitiatedDownload() */


#undef VIDNLD_C

